using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace SharpObjects.Cryptography.Symmetric 
{
	public class RijndaelProvider : ISymmetricCryptoProvider
	{
		protected Rijndael m_rij = null;
//		protected byte[] m_key = null; // 16 or 32 bytes
//		protected byte[] m_InitVector = null; // 16 bytes

		public RijndaelProvider()
		{
			m_rij = new RijndaelManaged();
			m_rij.Mode = CipherMode.CBC;
		}

		public RijndaelProvider(byte [] InitVector, byte[] key)
		{
			m_rij = new RijndaelManaged();
			m_rij.Mode = CipherMode.CBC;
			m_rij.IV = InitVector;
			m_rij.Key = key; 
		}

		public RijndaelProvider(string sUtf8InitVector, string sUtf8Key)
		{
			m_rij = new RijndaelManaged();
			m_rij.Mode = CipherMode.CBC;
			m_rij.IV = Encoding.UTF8.GetBytes(sUtf8InitVector);
			m_rij.Key = Encoding.UTF8.GetBytes(sUtf8Key);
		}

		public RijndaelProvider(string sInitVector, string sKey, System.Text.Encoding encoding)
		{
			m_rij = new RijndaelManaged();
			m_rij.Mode = CipherMode.CBC;
			m_rij.IV = encoding.GetBytes(sInitVector);
			m_rij.Key = encoding.GetBytes(sKey);
		}

		//#region ICryptoProvider Members


		public byte [] Encrypt(byte [] data)
		{
			MemoryStream str = new MemoryStream();
			ICryptoTransform encryptor = m_rij.CreateEncryptor();
			
			using(CryptoStream crystr = new CryptoStream(str, encryptor, CryptoStreamMode.Write))
			{
				crystr.Write(data, 0, data.Length);
				crystr.FlushFinalBlock();
				crystr.Close();
			}

			return str.ToArray();
		}

		public byte [] Decrypt(byte [] data)
		{
			MemoryStream str = new MemoryStream();

			ICryptoTransform decryptor = m_rij.CreateDecryptor();
			
			using(CryptoStream crystr = new CryptoStream(str, decryptor, CryptoStreamMode.Write))
			{
				crystr.Write(data, 0, data.Length);
				crystr.FlushFinalBlock();
				crystr.Close();
			}

			return str.ToArray();
		}

		public ICryptoKey CryptoKey 
		{
			get
			{
				ISymmetricKey key = new SymmetricKey();
				key.Key = m_rij.Key;
				key.IVector = m_rij.IV;

				return (ICryptoKey)key;
			}
			set
			{
				ISymmetricKey key = (ISymmetricKey)value;
				m_rij.Key = key.Key;
				m_rij.IV = key.IVector;
			}
		}

		//#endregion
	}
}
